package com.crazymaker.agent.demo.trace;

import com.crazymaker.agent.demo.aop.Listener;
import net.bytebuddy.agent.builder.AgentBuilder;
import net.bytebuddy.asm.Advice;
import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.dynamic.DynamicType;
import net.bytebuddy.utility.JavaModule;

import java.lang.instrument.Instrumentation;

import static net.bytebuddy.matcher.ElementMatchers.named;

public class AdviceTraceAgent {
    private final static String scanPackage = "com.crazymaker.circle.agent.biz";


    public static void premain(String agentArgs, Instrumentation instrumentation) {

        // Bytebuddy 的 API 用来修改
        AgentBuilder agentBuilder = new AgentBuilder.Default()
                .with(AgentBuilder.PoolStrategy.Default.EXTENDED)
                .with(AgentBuilder.InitializationStrategy.NoOp.INSTANCE)
//                .with(AgentBuilder.RedefinitionStrategy.REDEFINITION)
                .with(AgentBuilder.RedefinitionStrategy.RETRANSFORMATION)
                .with(new Listener(scanPackage))
                .disableClassFormatChanges();

        agentBuilder = agentBuilder
                // 匹配目标类的全类名
                .type(named("com.crazymaker.circle.agent.biz.Helloworld"))
                .transform(new AgentBuilder.Transformer() {
                    @Override
                    public DynamicType.Builder<?> transform(DynamicType.Builder<?> builder,
                                                            TypeDescription typeDescription,
                                                            ClassLoader classLoader,
                                                            JavaModule module) {

                        return builder.visit(
                                // 织入切面
                                Advice.to(TraceAspect.class)
                                        // 匹配目标类的方法
                                        .on(named("sayHello1").or(named("sayHello2").or(named("sayHello"))))
                        );
                    }
                });
        agentBuilder.installOn(instrumentation);
    }


}

